package kmeans.classificazione;


import java.text.DecimalFormat;
import java.util.List;
import java.util.Map;

import kmeans.documenti.Documento;


public class ValutazioneClassificatore {
	private String stampa;
	
	public ValutazioneClassificatore() {
		this.setStampa("");
	}
	
	/*calcola la matrice di contingenza classe predetta/classe reale */
	public int[][] valutazioneClassificatore(Map<String, List<Integer>> categorie, Map<Integer, List<Documento>> clas, String[] cat){
		int i,j, r = -1,c=-1;
		String stampa = this.getStampa();
		System.out.println("valutazione classificatore");
		stampa += "valutazione classificatore\n\n";
		stampa += "matrice di contingenza\n\n";
		stampa += "categorie predette/categorie effettive\n";
		int[][] matrice = new int[clas.keySet().size()+1][clas.keySet().size()+1];
		for(i=0; i<matrice.length; i++){
			for(j=0; j<matrice.length; j++){
				matrice[i][j] = 0;
			}
		}
		 
		for(Integer index: clas.keySet()){			
			for(Documento d: clas.get(index)){
				Integer classe = d.getClassePredetta();
				String classeVera =d.getCategoria();
				for(String s: categorie.keySet()){
					if(s.equals(classeVera)){
						for(j=0; j<cat.length; j++){
							if(cat[j].equals(s)){
								r = j; }
						}
					}
					if(categorie.get(s).contains(classe)){
						for(j=0; j<cat.length; j++){
							if(cat[j].equals(s)){
								c = j;
							}
						}
					}
				}
				matrice[r][c] += 1;
			}
		}
		int sum = 0;
		for(i=0; i<matrice.length-1; i++){
			sum = 0;
			for(j=0; j<matrice.length-1; j++){
				sum = sum + matrice[i][j];
			}
			matrice[i][matrice.length-1] = sum;
		}
		for(i=0; i<matrice.length-1; i++){
			sum = 0;
			for(j=0; j<matrice.length-1; j++){
				sum = sum + matrice[j][i];
			}
			matrice[matrice.length-1][i] = sum;
		}
		sum = 0;
		for(i=0; i<matrice.length-1; i++){
			sum = sum +matrice[matrice.length-1][i];
		}
		matrice[matrice.length-1][matrice.length-1] = sum;
		stampa += "\n\t\t";
		for(i=0; i<cat.length; i++){
			stampa += cat[i]+"\t\t";
		}
		stampa += "\n";
		for(i=0; i<matrice.length; i++){
			if(i<matrice.length-1){
				if(cat[i].equals("interest")|| cat[i].equals("money-fx") || cat[i].equals("acq")){
					if(cat[i].equals("acq")){
						stampa += cat[i]+"\t\t";
					}
					else{stampa += cat[i]+"\t";}
				}
				else{stampa += cat[i]+"\t\t";}
			}
			else{
				stampa += "\t\t";}
			
			for(j=0;j<matrice.length; j++){
				stampa += matrice[i][j]+"\t\t";
			}
			stampa += "\n";
		}
		this.setStampa(stampa);
		this.calcolo_accuratezza_TrueER(matrice);
		this.calcolo_precision_recall(matrice, cat);
		return matrice;
	}
	
	/*metodo per il calcolo dell'accuratezza e dell'error rate*/
	public void calcolo_accuratezza_TrueER(int[][] matrice){
		int i;
		String stampa = this.getStampa();
		
		DecimalFormat xFormat = new DecimalFormat("##0.000");
		int istanze = matrice[matrice.length-1][matrice.length-1];
		double s = 0;
		double te = 0;
		for(i=0; i<matrice.length-1; i++){
			s += matrice[i][i];	
			te += matrice[i][matrice.length-1]-matrice[i][i];
		}
		s = s/istanze;
		te = te/istanze;
		stampa += "\n\nAccuratezza: "+xFormat.format(s);
		stampa += "\nError rate: "+xFormat.format(te)+"\n\n";
		this.setStampa(stampa);
	}
	
	/*metodo per il calcolo della precision e della recall per ogni classe*/
	public double[][] calcolo_precision_recall(int[][] matrice, String[] categorie){
		int i;
		String stampa = this.getStampa();
		DecimalFormat xFormat = new DecimalFormat("##0.000");
		double[][] pr = new double[matrice.length-1][2];
		for(i=0; i<matrice.length-1; i++){
			if(matrice[matrice.length-1][i]==0){
				pr[i][0] = 0;
			}else{
				pr[i][0] = (double)matrice[i][i]/(double)matrice[matrice.length-1][i];
			}
			if(matrice[i][matrice.length-1]==0){
				pr[i][1] = 0;
			}
			else{
				pr[i][1] = (double)matrice[i][i]/(double)matrice[i][matrice.length-1];
			}
		}
		stampa += "\n\t\tPrecision\tRecall";
		for(i=0; i<matrice.length-1; i++){
			if(categorie[i].equals("interest") || categorie[i].equals("money-fx")){
				stampa += "\n"+categorie[i] + "\t"+ xFormat.format(pr[i][0]) +"\t\t" +xFormat.format(pr[i][1]);
			}
			else{
				stampa += "\n"+categorie[i] + "\t\t"+ xFormat.format(pr[i][0]) +"\t\t" +xFormat.format(pr[i][1]);
				}
		}
		stampa +="\n";
		this.setStampa(stampa);
		return pr;
	}


	public String getStampa() {
		return stampa;
	}


	public void setStampa(String stampa) {
		this.stampa = stampa;
	}

}
